#include "Game.h"
#include "Screen.h"
#include "Timer.h"
#include "EventPoller.h"
#include "DegToRad.h"
#include "ReportError.h"
#include "AntTweakBar.h"

#include <assert.h>


Game::Game() : m_State(nullptr), m_pCollisionSystem(nullptr)
{
 
}

void Game::Start()
{
	while(true)
	{
		Update();
		Draw();

		Screen::Instance()->Flip();
	}
}

void Game::LoadSettings(std::string FileName)
{
	File TempFile;

	if(!TempFile.OpenRead(FileName))
	{
		ReportError("Couldn't Open 'Settings.txt'");
	}

	if(!TempFile.GetInteger(&m_ResolutionX))
	{
		ReportError("Couldn't Find Resolution X Value in 'Settings.txt'");
	}

	if(!TempFile.GetInteger(&m_ResolutionY))
	{
		ReportError("Couldn't Find Resolution Y Value in 'Settings.txt'");
	}

	if(!TempFile.GetBool(&m_FullScreen))
	{
		ReportError("Couldn't Fullscreen Value in 'Settings.txt'");
	}
	
}

void Game::SaveSettings()
{
	//Some code from http://www.cplusplus.com/doc/tutorial/files/

	std::ofstream myfile;
	myfile.open ("Assets/Settings.txt");

	myfile << "#Resolution X Value\n" << m_ResolutionX << "\n\n";
	myfile << "#Resolution Y Value\n" << m_ResolutionY << "\n\n";
	myfile << "#Fullscreen\n" << m_FullScreen << "\n\n";

	myfile << "FileEnd\n";

}

GameObject* Game::GetObject(int Id)
{
	GameObjectsMap::iterator it;
	it = m_objects.find(Id);

	return it->second;
}

void Game::Draw()
{
	m_State->Draw();
	TheTweakBar::Instance()->Draw();
}

void Game::Update()
{
	TheTimer::Instance()->Update();
	TheEventPoller::Instance()->Update();
	m_State->Update();
}



void Game::SetGameState(GameState* theGameState)
{
	if (m_State != theGameState)
	{
		if (m_State)
		{
			m_State->OnDeactivated();
		}

		m_State = theGameState;
		m_State->OnActivated();
	}
}

void Game::DrawGameObjects()
{
	for (GameObjectsMap::iterator it = m_objects.begin();
		it != m_objects.end(); ++it)
	{
		it->second->Draw();
	}

}

void Game::UpdategameObjects()
{
	for (GameObjectsMap::iterator it = m_objects.begin();
		it != m_objects.end(); ++it)
	{
		it->second->Update();
	}
	//UpdateCollisions();
}

void Game::AddGameObject(int id, GameObject* g)
{
	assert(m_objects.find(id) == m_objects.end());
	m_objects[id] = g;
}

void Game::SetCollisionSystem(CollisionSystem* pCs)
{
	m_pCollisionSystem = pCs;
}

void Game::UpdateCollisions()
{
	//assert(m_pCollisionSystem);

	m_pCollisionSystem->
		Update(&m_objects);
}

void Game::HandleCollision(GameObject* g1,GameObject* g2)
{
	// create a Key_Type from 2 strings

	// 1st string is the type of g1
	std::string s1 = g1->GetTypeName();
	// 2nd string is the type of g2
	std::string s2 = g2->GetTypeName();
	Key_Type k(s1, s2);

	CollisionMap::iterator it = m_CollisionMap.find(k);

	if(it == m_CollisionMap.end())
	{
		std::swap(k.first, k.second);
		it = m_CollisionMap.find(k);
		if(it == m_CollisionMap.end())
		{
			//Don't Care
		}
		else
		{
			CollisionHandler ch = it->second;
			ch(g2, g1);
		}
	}
	else
	{
		CollisionHandler ch = it->second;
		ch(g1, g2);
	}
}

bool Game::AddCollisionHandler(const std::string& s1,const std::string& s2, CollisionHandler ch)
{
	Key_Type k(s1, s2);
	m_CollisionMap[k] = ch;
	return true;
}


Game::~Game()
{
	SaveSettings();
}
